package cloudeval.spec.runtime

import cloudeval.spec.DataCenterSpec
import cloudeval.spec.EvaluationSpec
import cloudeval.spec.VMScheduleStrategySpec
import cn.edu.neu.vmmigeval.cloud.entity.DataCenter
import cn.edu.neu.vmmigeval.cloud.entity.DataCenterBroker
import cn.edu.neu.vmmigeval.cloud.policy.WorkloadModel
import cn.edu.neu.vmmigeval.evaluation.Measure

/**
 * The simulation.
 *
 * @author yfwz100
 */
class Simulation implements Runnable {

    // the specification/registry.

    DataCenterSpec dataCenterSpec
    VMScheduleStrategySpec vmScheduleStrategySpec

    List<Measure> measures

    Map<String, EvaluationSpec.Symbol> metrics

    // internal constant.

    int clockCycles = 1000;

    @Override
    void run() {
        Map<String, Map<String, Double>> table = new HashMap<>()
        dataCenterSpec.hostClusterSpecMap.each { hostClusterName, hostClusterSpec ->
            dataCenterSpec.VMSpecMap.each { vmSpecName, vmSpec ->
                dataCenterSpec.workloadSpecMap.each { workloadName, workloadSpec ->
                    vmScheduleStrategySpec.strategies.each { strategyName, vmAllocation ->
                        DataCenter dataCenter = hostClusterSpec.createDataCenter()
                        dataCenter.vmAllocation = vmAllocation
                        DataCenterBroker broker = vmSpec.createDataCenterBroker(dataCenter)
                        WorkloadModel workload = workloadSpec.createWorkloadModel()
                        int clock = 0;
                        while (clock++ < clockCycles) {
                            println("执行第 " + clock + " 个周期")
                            // update the data center and broker
                            dataCenter.updateAllMigration()
                            broker.updateVmsProcessing(clock)
                            dataCenter.updateHostsProcessing(clock)
                            // collect data.
                            measures*.process(clock, broker, dataCenter)
                            // update workload.
                            workload.addCloudlets(clock, broker, dataCenter)
                        }
                        def name = [hostClusterName, vmSpecName, workloadName, strategyName].join('.')
                        table[name] = metrics.collectEntries { k, v -> [k, v.value] }
                    }
                }
            }
        }
        // process the report.
        generateReport()
    }

    private void generateReport() {

    }
}
